package com.ruoyi.web.controller.social.program;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.Contract;
import com.ruoyi.common.core.domain.entity.Program;
import com.ruoyi.common.core.domain.entity.ProgramRecord;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.mapper.ContractMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.mapper.SysUserPostMapper;
import com.ruoyi.system.service.ProgramRecordService;
import com.ruoyi.system.service.ProgramService;
import com.ruoyi.system.service.resp.ProgramBingStatDTO;
import com.ruoyi.system.service.resp.ProgramStatDTO;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/social/program/program")
public class ProgramController extends BaseController {
    @Resource
    private ProgramService programService;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private SysUserPostMapper sysUserPostMapper;

    @Resource
    private ContractMapper contractMapper;

    @Log(title = "项目基本信息导出", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Program program) {
        Long userId = SecurityUtils.getUserId();
        SysUser sysUser = sysUserMapper.selectUserById(userId);
        List<Long> postIds = sysUserPostMapper.getUserPosts(SecurityUtils.getUserId());
        if (CollectionUtils.isEmpty(postIds)) {
            // 默认只能看到自己的数据
            program.setCreator(userId);
            program.setDept(null);
        } else if (postIds.stream().anyMatch(p -> p < 7)) {
            // 副主任以上能看到所有数据
            program.setCreator(null);
            program.setDept(null);
        } else if (postIds.stream().anyMatch(p -> p <= 8 && p >= 7)) {
            // 科长副科长只能看到自己科室的数据
            program.setCreator(null);
            program.setDept(sysUser.getDeptId());
        } else {
            // 其他人只能看到自己科室的自己的数据
            program.setCreator(userId);
            program.setDept(sysUser.getDeptId());
        }
        List<Program> list = programService.selectProgramList(program);
        ExcelUtil<Program> util = new ExcelUtil<Program>(Program.class);
        util.exportExcel(response, list, "项目列表");
    }

    @Log(title = "项目基本信息", businessType = BusinessType.OTHER)
    @GetMapping("/list")
    public TableDataInfo list(Program program) {
//        Long userId = SecurityUtils.getUserId();
//        SysUser sysUser = sysUserMapper.selectUserById(userId);
//        List<Long> postIds = sysUserPostMapper.getUserPosts(SecurityUtils.getUserId());
//        if (CollectionUtils.isEmpty(postIds)) {
//            // 默认只能看到自己的数据
//            program.setCreator(userId);
//            program.setDept(null);
//        } else if (postIds.stream().anyMatch(p -> p < 7)) {
//            // 副主任以上能看到所有数据
//            program.setCreator(null);
//            program.setDept(null);
//        } else if (postIds.stream().anyMatch(p -> p <= 8 && p >= 7)) {
//            // 科长副科长只能看到自己科室的数据
//            program.setCreator(null);
//            program.setDept(sysUser.getDeptId());
//        } else {
//            // 其他人只能看到自己科室的自己的数据
//            program.setCreator(userId);
//            program.setDept(sysUser.getDeptId());
//        }
        startPage();
        List<Program> list = programService.selectProgramList(program);
        return getDataTable(list);
    }

//    private void fillContractInfo(List<Program> list) {
//        if (CollectionUtils.isEmpty(list)) {
//            return;
//        }
//        Map<Long, Contract> contractMap = contractMapper.selectByIds(list.stream().map(Program::getContract).collect(Collectors.toList())).stream().collect(Collectors.toMap(Contract::getId, c -> c));
//        for (Program program : list) {
//            program.setAbst(Optional.ofNullable(contractMap.get(program.getContract())).map(Contract::getAbst).orElse(null));
//            program.setContractAmount(Optional.ofNullable(contractMap.get(program.getContract())).map(Contract::getAmount).orElse(null));
//            program.setDuration(Optional.ofNullable(contractMap.get(program.getContract())).map(Contract::getDuration).orElse(null));
//            program.setCompany(Optional.ofNullable(contractMap.get(program.getContract())).map(Contract::getCompany).orElse(null));
//        }
//    }

    @GetMapping("/data")
    public TableDataInfo list() {
        Program program = new Program();
        program.setStatus("进行中");
        List<Program> list = programService.selectProgramList(program);
        return getDataTable(toDTO(list));
    }

    @GetMapping("/bing")
    public AjaxResult bing() {
        ProgramBingStatDTO programBingStatDTO = new ProgramBingStatDTO();
        Program program = new Program();
        program.setStatus("进行中");
        List<Program> list = programService.selectProgramList(program);
        programBingStatDTO.setDoingCnt(list.size());
        program.setStatus("验收中");
        list = programService.selectProgramList(program);
        programBingStatDTO.setCheckingCnt(list.size());
        program.setStatus("已完成");
        list = programService.selectProgramList(program);
        programBingStatDTO.setFinishedCnt(list.size());
        return success(programBingStatDTO);
    }

    @Log(title = "项目基本信息All", businessType = BusinessType.OTHER)
    @GetMapping("/listAll")
    public TableDataInfo listAll(Program examinePlan) {
        List<Program> list = programService.selectAll(examinePlan);
        return getDataTable(list);
    }

    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable Long id) {
        return success(programService.selectById(id));
    }

    @Log(title = "项目基本信息", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult add(@Validated @RequestBody Program program) {
        // checkAdd(program);
        Long userId = SecurityUtils.getUserId();
        program.setCreator(userId);
        program.setDept(Optional.ofNullable(sysUserMapper.selectUserById(userId)).map(SysUser::getDeptId).orElse(null));
        program.setCreateBy(SecurityUtils.getLoginUser().getUser().getNickName());
        Boolean result = programService.createProgramPlan(program);
        //自动生成6条明细
        List<String> strings = Arrays.asList("请示", "纪要", "合同", "验收报告", "结算审核", "发票");
        for (String s : strings) {
            ProgramRecord programRecord = new ProgramRecord();
            programRecord.setProgramId(program.getId());
            programRecord.setContent(s);
            programRecord.setStatus("否");
            programRecord.setRecordTime(new Date());
            programRecord.setCreateTime(new Date());
            programRecord.setCreateBy(SecurityUtils.getNickName());
            programRecordService.createProgramRecord(programRecord);
        }
        if (result) {
            return success();
        }
        return error();
    }

    private void checkAdd(Program program) {
        if (program == null) {
            throw new ServiceException("没有项目信息");
        }
        if (program.getContract() == null) {
            throw new ServiceException("没有合同信息");
        }
    }

    @Log(title = "项目基本信息", businessType = BusinessType.UPDATE)
    @PutMapping
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult edit(@Validated @RequestBody Program examinePlan) {
        examinePlan.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
        Boolean result = programService.updateProgramPlan(examinePlan);
        Program search = programService.selectById(examinePlan.getId());
        if (search == null || !search.getCreateBy().equals(examinePlan.getUpdateBy())) {
            throw new BaseException("该单据由" + search.getCreateBy() + "创建，您无法修改");
        }
        if (result) {
            return success();
        }
        return error();
    }

    @Resource
    private ProgramRecordService programRecordService;

    @Log(title = "考核方案", businessType = BusinessType.DELETE)
    @DeleteMapping("/{id}")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult remove(@PathVariable Long id) {
        Program search = programService.selectById(id);
        if (search == null || !search.getCreateBy().equals(SecurityUtils.getLoginUser().getUser().getNickName())) {
            throw new BaseException("该单据由" + search.getCreateBy() + "创建，您无法删除");
        }
        return toAjax(programService.deleteById(id));
    }

    private List<ProgramStatDTO> toDTO(List<Program> programList) {
        if (CollectionUtils.isEmpty(programList)) {
            return Collections.emptyList();
        }
        return programList.stream().filter(Objects::nonNull).map(p -> {
            ProgramStatDTO programStatDTO = new ProgramStatDTO();
            programStatDTO.setName(p.getName());
            List<ProgramRecord> programRecords = programRecordService.selectProgramRecordList(ProgramRecord.builder().programId(p.getId()).build());
            ProgramRecord record = CollectionUtils.isEmpty(programRecords) ? null : programRecords.get(0);
            programStatDTO.setLatestRecordTime(Optional.ofNullable(record).map(BaseEntity::getCreateTime).orElse(null));
            programStatDTO.setLatestRecordContent(Optional.ofNullable(record).map(ProgramRecord::getContent).orElse(null));
            return programStatDTO;
        }).collect(Collectors.toList());
    }


}
